#include "cargadorDeArchivos.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string>
using namespace std;
#define NOMBRE_ARCHIVO_DICCIONARIO "diccionario.txt"
#define NOMBRE_ARCHIVO_APARICIONES "apariciones.txt"
#define NOMBRE_ARCHIVO_TRIGRAMAS "trigramas.txt"
#define SEPARADOR_PRIMERAS_PALABRAS 'P'
#define SEPARADOR_SEGUNDAS_PALABRAS 'S'
#define SEPARADOR_TERCERAS_PALABRAS 'T'
#define SEPARADOR_PALABRA_FRECUENCIA 'F'

void cargarDiccionarioAMedias(diccionario_t* dic){
	FILE* archivoDiccionario = fopen(NOMBRE_ARCHIVO_DICCIONARIO ,"r");

	int id;
	termino_t termino;
	char lineaDic_c[40];

	string palabra;

	while(!feof(archivoDiccionario)){
		fscanf(archivoDiccionario, "%[^\n]\n", lineaDic_c);
		vector<string> vecDic;
		split(lineaDic_c, ' ', &vecDic);
		id = atoi(vecDic.at(0).c_str());
		palabra = vecDic.at(1);

		termino_t termino;
		termino.index = id;

		dic->mapa.insert(pair<string, termino_t>(palabra, termino));
	}
	fclose(archivoDiccionario);
}

void cargarDiccionario(
		diccionario_t* dic,
		diccionarioPorIndice_t* dicPorIndice,
		set<int>* testSet){

	dic->total = 0;
	FILE* archivoDiccionario = fopen(NOMBRE_ARCHIVO_DICCIONARIO, "r");
	FILE* archivoApariciones = fopen(NOMBRE_ARCHIVO_APARICIONES, "r");
	int id, freq;
	string lineaAp, lineaDic;
	char lineaAp_c[1000000];
	char lineaDic_c[40];

	while(!dicPorIndice->empty())
		dicPorIndice->erase(dicPorIndice->begin());

	while((!feof(archivoDiccionario)) and (!feof(archivoApariciones))){
		fscanf(archivoDiccionario, "%[^\n]\n", lineaDic_c);
		fscanf(archivoApariciones, "%[^\n]\n", lineaAp_c);
		lineaAp = lineaAp_c;
		lineaDic = lineaDic_c;
		vector<string> vecDic;
		split(lineaDic, ' ', &vecDic);
		id = atoi(vecDic.at(0).c_str());

		termino_t termino;
		if(testSet->find(id) != testSet->end()){
			freq = atoi(vecDic.at(2).c_str());
			string palabra = vecDic.at(1);
			termino.index = id;
			termino.frecuencia = freq;
			vector<string> vectorAp;
			split(lineaAp, ' ', &vectorAp);
			termino.sonAparicones = (atoi(vectorAp[0].c_str()) == 1);
			termino.bitSetDeFragmentos.reset();
			for(size_t i = 1; i< vectorAp.size(); i++)
				termino.bitSetDeFragmentos[atoi(vectorAp.at(i).c_str())] = true;
				if(! termino.sonAparicones) termino.bitSetDeFragmentos.flip();
				dic->mapa.insert(pair<string, termino_t>(palabra, termino));
				dicPorIndice->insert(pair<int, string>(id, palabra));
			}
		dic->total += freq;
		}
	fclose(archivoDiccionario);
	fclose(archivoApariciones);

}



//----------------
bool estaEnMapa2(int key, map<int, map<int, int> >* mapa){
	//for(map<int, map<int, int> >::iterator it = mapa->begin() ; it != mapa->end() ; ++it)
	//	if(it->first == key) return true;
	//return false;
	return (mapa->find(key) != mapa->end());
}

bool estaEnMapa3(int key, map<int, map<int, map<int, int> > >* mapa){
	//for(map<int, map<int, map<int, int> > >::iterator it = mapa->begin() ; it != mapa->end() ; ++it)
	//	if(it->first == key) return true;
	//return false;
	return (mapa->find(key) != mapa->end());
}


void agregar(mapaDeTrigramas_t* mapa, int pri, int seg, int ter, int freq){
	if(estaEnMapa3(pri, mapa)){

		if(estaEnMapa2(seg, &(mapa->at(pri)))){
			mapa->at(pri).at(seg).insert(pair<int, int>(ter, freq));
			return;
		}
		else{
			map<int, int> newMapii;
			newMapii.insert( pair<int, int>(ter, freq) );
			mapa->at(pri).insert(pair<int, map<int, int> >(seg, newMapii));
			return;
		}
	}
	else{
		map<int, int> newMapii;
		newMapii.insert(pair<int, int>(ter, freq));
		map<int, map<int, int> > newMapim;
		newMapim.insert(pair<int, map<int, int> >(seg, newMapii));
		mapa->insert(pair<int, map<int, map<int, int> > >(pri, newMapim));
		return;
	}
}

// cada linea: p1-S2-p2-S3-p3-SPF-fr-S3-p3-SPF-fr-S3-p3-SPF-fr-S2-p2-S3-p3-SPF-fr-S3-p3-SPF-fr-S3-p3-SPF-fr-S1-

void cargarTrigramas(set<int>* testSet, mapaDeTrigramas_t* mapaDeTrigramas){
	FILE* archivoDeTrigramas = fopen(NOMBRE_ARCHIVO_TRIGRAMAS, "r");
	fgetc(archivoDeTrigramas);

	char* linea = new char[74000000];

	while(!feof(archivoDeTrigramas)){
		vector< vector< string > > matrizSeparada;
		fscanf(archivoDeTrigramas, "%[^P]P", linea);

		vector<string> vectorSeparado;
		split(linea, SEPARADOR_SEGUNDAS_PALABRAS, &vectorSeparado);

		int primeraPalabra = atoi(vectorSeparado.at(0).c_str());

		if(testSet->find(primeraPalabra) != testSet->end()){
			int tam = vectorSeparado.size();

			for(int i = 1 ; i < tam ; i++){
				vector<string> veci;
				split(vectorSeparado.at(i), SEPARADOR_TERCERAS_PALABRAS, &veci);
				matrizSeparada.push_back(veci);
			}

			int segundaPalabra;
			int terceraPalabra;
			int frecuencia;
			int cantidadDeVectores = matrizSeparada.size();

			for(int i = 0; i < cantidadDeVectores ; i++){
				vector<string> x = matrizSeparada.at(i);
				segundaPalabra = atoi(x.at(0).c_str());

				for(size_t i = 1; i < x.size(); i++){
					vector<string> palabraVsFrecuencia;
					split(x.at(i), SEPARADOR_PALABRA_FRECUENCIA, &palabraVsFrecuencia);
					terceraPalabra = atoi(palabraVsFrecuencia.at(0).c_str());

					frecuencia = atoi(palabraVsFrecuencia.at(1).c_str());
					agregar(mapaDeTrigramas, primeraPalabra, segundaPalabra, terceraPalabra, frecuencia);

				}
			}
		}
	}
	delete[] linea;
	fclose(archivoDeTrigramas);


}

bool palabraApareceEnDiccionario(string palabra, diccionarioPorIndice_t* dicPorInd){
	for(map<int, string>::iterator it = dicPorInd->begin();
			it != dicPorInd->end(); ++it){
		if(it->second == palabra) return true;
	}
	return false;
}


